package pers.corvey.crawler.util;

import java.util.concurrent.locks.AbstractQueuedSynchronizer;

/**
 * 限制单位时间内执行次数工具类
 * @author Corvey
 */
public class LimitExecuteUtils {
	
	/**
	 * 单位时间内允许执行次数
	 */
	private static final int LIMIT_TIMES = 38;
	/**
	 * 单位时间长度（毫秒）
	 */
	private static final long LIMIT_UNIT_TIME = 60 * 1000;
	private static final Sync sync = new Sync();
	private static Thread daemonThread;
	
	public static void limitExecute() {
		sync.acquireShared(1);
	}
	
	public static void init() {
		daemonThread.setDaemon(true);
		daemonThread.start();
	}
	
	private static final class Sync extends AbstractQueuedSynchronizer {
		private static final long serialVersionUID = 4122088104727575992L;
		Sync() {
			setState(LIMIT_TIMES);
			daemonThread = new Thread(()->{
				for (;;) {
					try {
						Thread.sleep(LIMIT_UNIT_TIME);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					setState(LIMIT_TIMES);
					releaseShared(1);
				}
			});
		}
		@Override
		protected int tryAcquireShared(int count) {
			for (;;) {
				int state = getState();
				int newState = state - 1;
				if (newState < 0 || compareAndSetState(state, newState)) {
					return newState;
				}
			}
		}
		@Override
		protected boolean tryReleaseShared(int count) {
			return true;
		}
	}
}
